﻿/*
1、QCheckBox复选框（复选按钮）
（1）状态变化信号stateChanged
（2）三种状态：选中、未选中、部分选中
（3）setTristate(ture)是否开启三态
（4）获取当前复选框的状态
	Qt::CheckState swimState = ui.chbSwim->checkState();
2、QRadioButton 单选按钮
3、QButtonGroup按钮组
	当有一组按钮时，可以共用一个槽函数，在槽函数中做判断逻辑处理，此时需要使用按钮组控件。
	可以放到ButtonGroup中的按钮有QPushButton、QToolButton、QCheckBox、QRadioButton。
（1）addButton()将按钮添加到按钮组并设置id
（2）button()获取按钮
（3）设置按钮互斥setExclusive()
（4）按钮组中按钮点击的信号buttonClicked()
二、输入类控件
1、QComboBox组合框
组合框是下拉列表控件，提供一个下拉列表供用户选择，除了选择它还是可以输入。
常用方法：
（1）int currentIndex()返回当前项的序号（下标）,从0开始
（2）QString currentText()返回当前项的文本
（3）QVariant currentData()返回当前项的关联数据（用户数据）
（4）QString itemText(int index)返回指定项的文本
（5）int count() 返回下拉项的数目
信号：
（1）currentIndexChanged()重载，下拉项的索引变化时发出该信号
（2）currentTextChanged(),下拉项的文本变化时发出该信号

2、QFontComboBox字体组合框
设置字体过滤器方法setFontFilters(QFontComboBox::FontFilters filters)的参数说明如下：
	QFontComboBox::AllFonts  显示所有字体
	QFontComboBox::ScalableFonts 显示可缩放字体
	QFontComboBox::NonScalableFonts 显示不可缩放字体
	QFontComboBox::MonospacedFonts 显示等宽字体
	QFontComboBox::ProportionalFonts 显示比例字体
3、QLineEdit行编辑器
它是一个单行文本编辑器，允许用户输入和编辑单行文本内容，且提供了一系列功能，包括copy、paste、cut
Undo等。
（1）显示模式echoMode:Normal正常模式，正常显示输入的信息
         Password显示密码样式，用小黑点或*显示输入的信息
		 NoEcho不显示任何输入内容
		 PasswordEchoOnEdit在编辑时显示正常字符，其他情况显示密码样式
（2）焦点策略focusPolicy:
        StrongFocus通过Tab键和左键单击获取焦点
		TabFocus 通过Tab键获取焦点
		ClickFocus通过左键单击获取焦点
		WheelFocus通过鼠标滚轴获取焦点
		NoFocus不接受焦点（不能进行输入）  
（3）正则验证器
（4）对齐方式
（5）添加图标
（6）自动补全
（7）最大长度、提示信息等
（8）QLineEdit的常用信号：
	textChanged()信号——当编辑框的文本内容发生变化时，发出该信号。
	当通过setText()给编辑框设置文本时，会发出textChanged信号。
	textEdited()信号——当文本被编辑时发出该信号。当通过setText()给编辑框设置文本时，
	不会发出textEdited信号。
	editingFinished()当编辑完文本按下回车键或输入焦点离开编辑框时，发出该信号。
 

4、正则表达式
	正则表达式是一种文本模式，包括普通字符和特殊字符。正则表达式是使用单个字符串来描述、匹配一系列满足某个语法规则的字符串，
通常被用来检索、替换那些满足规则的文本。
	Regexp由表达式、量词和断言组成。最简单的一个字符x或5，而一组字符可以使用方括号括起来，例如[ABC],意思是匹配一个A、或一个B或一个C，
可以简写为[A-C]。
	一个量词指定了必须要匹配的表达出现的次数，例如x{1,1}，必须匹配且只能匹配一个字符x。x{1,5}意思是匹配一系列字符x,至少包含一个字符x,
	最多包含五个字符x。
	如果要匹配0到99之间的整数，可以使用正则表达式[0-9]{1,2}。这个表达式也可以匹配字符串中间的整数,例如：hello93world。
	如果想匹配的整数是整个字符串（例如：93），需要使用断言“^”和“$”。
	当^在正则表达式中作为第一个字符出现时，意思是从字符串的开始进行匹配，$在正则表达式中作为最后一个字符时，意思是匹配到字符串的结尾。
	故只想匹配两位数字的正则表达式是：^[0-9]{1,2}$

	[0-9]可以使用\d表示，x{1,1}可以使用x表示，要匹配[0-99] 可以写成 ^\d{1,2}$ 
	如果要任意位数的匹配数字和字符，正则表达式 ^[0-9A-Za-z]*$

	正则表达式中的括号：
	小括号()，匹配括号中的内容，通常与|（或）符号一块使用，表示匹配多项内容
	中括号[]，匹配指定范围的内容
	大括号{m,n} 匹配次数，匹配最少m次，最多n次

5、 QTextEdit文本块编辑框
    QTextEdit是一种高级的文本查看编辑器，可以显示图片、列表、表格等内容。
	两种设置文本的方式：
	（1）setPlainText()；每次设置内容时会将之前的内容清空；
	（2）insertPlainText();不清空，追加设置内容。
	（3）QString toPlainText();获取文本内容
	信号：textChanged，文本内容发生变化时发出该信号。
6、时间日期控件
	(1)从控件上获取日期时间
	ui.timeEdit->time();
	ui.dateEdit->date();
	ui.dateTimeEdit->dateTime();
   （2）从QTime到QString的转换
   QString strTime = QTime::toString("HH:mm:ss"),注意格式
   （3）从QString到QTime的转换
   QTime tm = QTime::fromString(strTime,"HH:mm:ss")
   (4)ui.dateEdit->setCalendarPopup(true);
   (5)常用信号：
   dateChanged()
   dateTimeChanged()
   timeChanged() 当时间日期发生变化时发出该信号
   editingFinished()当控件失去焦点时发出该信号。
7、QScrollBar滚动条控件
  水平垂直滚动条允许用户访问超出显示范围的内容。一般不单独使用，需要结合QScrollArea或窗体使用。

8、QSlider滑动条
   滑块是用于控制有界值，例如调整音量、透明度等。
   常用函数：
   （1）setValue()设置当前值
   （2）setRange()设置调整范围
   （3）setMinmum()和setMaxmum()用于设置最小值和最大值
   （4）setTickPosition()设置刻度的位置 tickPosition() 获取刻度位置
   （5）setTickInterval()设刻度的间隔   tickInterval() 获取刻度间隔

9、QSpinBox旋转框
  常用方法同QSlider
  设置步长 setSingleStep()
*/

#include "Qt7ButtonsApp.h"
#include <QMessageBox>
#include <QDebug>
#include <QButtonGroup>
#include <QAction>
#include <QCompleter>
#include <QScrollBar>

Qt7ButtonsApp::Qt7ButtonsApp(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
	ui.rbtnMale->setChecked(true);
	m_pButtonGroup = new QButtonGroup(this);
	// 开启多选一属性
	m_pButtonGroup->setExclusive(true);
	// addButton将按钮添加到按钮组中，参数1是按钮对象，参数2是按钮的id
	m_pButtonGroup->addButton(ui.rbtnFemale, 0);
	m_pButtonGroup->addButton(ui.rbtnMale, 1);

	// 组合框初始化方式1
// 	ui.cbxProvince->addItem(QStringLiteral("新疆"));
// 	ui.cbxProvince->addItem(QStringLiteral("山东省"));
// 	ui.cbxProvince->addItem(QStringLiteral("陕西省"));
// 	ui.cbxProvince->addItem(QStringLiteral("北京市"));

	// 组合框初始化方式2，初始化多项内容
// 	QStringList provinceList;
// 	provinceList << QStringLiteral("上海市") << QStringLiteral("北京市") << QStringLiteral("山东省") << QStringLiteral("陕西省");
// 	ui.cbxProvince->addItems(provinceList);

	// 组合初始化方式3，下拉项带图标
	//QIcon icon1(":/Qt7ButtonsApp/images/1.png");
	//QIcon icon2(":/Qt7ButtonsApp/images/2.png");
	//QIcon icon3(":/Qt7ButtonsApp/images/3.png");
	//ui.cbxProvince->addItem(icon1, QStringLiteral("北京市"));
	//ui.cbxProvince->addItem(icon2, QStringLiteral("上海市"));
	//ui.cbxProvince->addItem(icon3, QStringLiteral("重庆市"));


	// 组合框初始化方式4，带有用户数据
	QMap<QString, int>cityZoneMap;
	cityZoneMap.insert(QStringLiteral("北京市"), 100);
	cityZoneMap.insert(QStringLiteral("天津市"), 110);
	cityZoneMap.insert(QStringLiteral("石家庄市"), 120);
	cityZoneMap.insert(QStringLiteral("济南市"), 130);
	for each(const QString &key in cityZoneMap.keys())
	{
		ui.cbxProvince->addItem(key, cityZoneMap.value(key));
	}

	// currentIndex
	// 将复选按钮的状态变化信号和对应的槽函数进行关联
	connect(ui.chbRun, &QCheckBox::stateChanged, this, &Qt7ButtonsApp::stateChangedSlot);
	connect(m_pButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(buttonGroupSlot(int)));
	// 身份组合框项变化信号和槽函数关联
	//connect(ui.cbxProvince, SIGNAL(currentIndexChanged(int)), this, SLOT(provinceComboBoxChangedSlot(int)));
	//connect(ui.cbxProvince, SIGNAL(currentIndexChanged(QString)), this, SLOT(provinceComboBoxChangedStringSlot(QString)));

	// 手动调用槽函数，在QLabel上显示第一项内容
	//provinceComboBoxChangedSlot(0);
	//provinceComboBoxChangedStringSlot(QStringLiteral("北京市"));

	// 字体组合框，设置字体
// 	ui.cbxFont->setCurrentFont(QFont(QStringLiteral("黑体")));
// 	// 获取当前的字体
// 	QFont font = ui.cbxFont->currentFont();
// 	// 给QLabel设置字体
// 	ui.labelFont->setFont(font);
	// 设置字体过滤器
	ui.cbxFont->setFontFilters(QFontComboBox::ScalableFonts);

	// QLineEdit设置显示模式
	ui.lineEditNormal->setEchoMode(QLineEdit::Normal);
    // 设置获取焦点策略
	ui.lineEditNormal->setFocusPolicy(Qt::StrongFocus);
	// 设置最大输入长度
	ui.lineEditNormal->setMaxLength(15);
	ui.lineEditPassword->setMaxLength(6);
	// 设置提示信息
	ui.lineEditNoFocus->setPlaceholderText(QStringLiteral("不能输入内容"));
	// 只输入数字，验证器
	QValidator *pNumVal = new QIntValidator(100, 999, this);
	ui.lineEditNumber->setValidator(pNumVal);
	// QString转换为int
	ui.lineEditNumber->setText(QString::number(11200));

	// 只能输入数字、小数点、负号
	QRegularExpression reg("^[0-9.-]+$"); //创建正则表达式对象 
	QRegularExpressionValidator *regVdtor = new QRegularExpressionValidator(this); // 创建正则表达式验证器
	regVdtor->setRegularExpression(reg);
	ui.lineEditPoint->setValidator(regVdtor);
	// 手机号正则表达式
	QRegularExpression regPhone("^1([3587][12345678])[0-9]{8}$");
	QRegularExpressionValidator *regPhoneVdt = new QRegularExpressionValidator(this);
	regPhoneVdt->setRegularExpression(regPhone);
	ui.lineEditPhoneNo->setValidator(regPhoneVdt);
	// 右对齐
	ui.lineEditPoint->setAlignment(Qt::AlignRight);
	// 居中对齐
	ui.lineEditPhoneNo->setAlignment(Qt::AlignCenter);
	// 给lineedit增加图标
	QAction *userAction = new QAction(ui.lineEditPhoneNo);
	userAction->setIcon(QIcon(":/Qt7ButtonsApp/images/1.png"));
	// 参数2不能遗漏，否则图标不能显示
	ui.lineEditPhoneNo->addAction(userAction,QLineEdit::TrailingPosition);
	// 自动补全
	QStringList strList;
	strList << "Qt" << "Qt Assist" << "Qt designer" << "Qt liguist";
	QCompleter *pCom = new QCompleter(strList,this);
	pCom->setCaseSensitivity(Qt::CaseInsensitive);
	ui.lineEditNormal->setCompleter(pCom);

	initTextEdit();

	// 点击滚动条未实现窗口滚动
// 	this->setGeometry(0, 0, 800, 480);
// 	// 水平滚动条
// 	m_pHorScrollBar = new QScrollBar(Qt::Horizontal, this);
// 	m_pHorScrollBar->setGeometry(0, 450, 800, 30);
// 	// 竖直滚动条
// 	m_pVerScrollBar = new QScrollBar(Qt::Vertical, this);
// 	m_pVerScrollBar->setGeometry(770, 0, 30, 480);

	// 滑块调整颜色值，将调整后的颜色作为textEdit的背景色
	ui.hsRed->setRange(0, 255);
	ui.hsRed->setValue(5);
	ui.hsRed->setTickInterval(10);

	ui.hsGreen->setMinimum(0);
	ui.hsGreen->setMaximum(255);
	ui.hsGreen->setValue(0);
	ui.hsGreen->setTickInterval(15);

	ui.hsBlue->setRange(0, 255);
	ui.hsBlue->setValue(20);
	ui.hsBlue->setTickInterval(20);

	connect(ui.hsRed, &QSlider::valueChanged, this, &Qt7ButtonsApp::sliderValueChangeSlot);
	connect(ui.hsBlue, &QSlider::valueChanged, this, &Qt7ButtonsApp::sliderValueChangeSlot);
	connect(ui.hsGreen, &QSlider::valueChanged, this, &Qt7ButtonsApp::sliderValueChangeSlot);

	ui.spinBox->setRange(0, 255);
	ui.spinBox->setSingleStep(10);

}

Qt7ButtonsApp::~Qt7ButtonsApp()
{}

void Qt7ButtonsApp::initTextEdit()
{
	//// 获取块编辑框的调色板
	//QPalette pal = ui.textEdit->palette();
	//// 设置画刷，填充背景色
	//pal.setBrush(QPalette::Base, QColor("#278CB8"));
	//// 取消继承父类的背景样式，允许自己填充颜色
	//ui.textEdit->setAutoFillBackground(true);
	//// 给textEdit设置调色板
	//ui.textEdit->setPalette(pal);


	// 给TextEdit设置背景图片
	QString strFileName = "C:\\Users\\dulin\\Desktop\\testimage\\feather.jpg";
	QPalette pal = ui.textEdit->palette();
	// QPixmap(strFileName)创建图片对象，scaled()缩放图片
	pal.setBrush(QPalette::Base, QPixmap(strFileName).scaled(ui.textEdit->size()));
	ui.textEdit->setAutoFillBackground(true);
	ui.textEdit->setPalette(pal);

	// 设置日期控件和日期时间控件显示日历
	ui.dateEdit->setCalendarPopup(true);
	ui.dateTimeEdit->setCalendarPopup(true);

}

void Qt7ButtonsApp::on_chbSwim_clicked()
{
	QString strText = ui.chbSwim->text();
	QMessageBox::information(this, QStringLiteral("选择"), strText);

	// 获取复选框当前的状态
	Qt::CheckState swimState = ui.chbSwim->checkState();
	qDebug() << swimState;

}

void Qt7ButtonsApp::stateChangedSlot(int nState)
{
	if (nState == Qt::Unchecked)
	{
		QMessageBox::information(this, QStringLiteral("状态"), QStringLiteral("跑步未被选中"));
	}
	else if (Qt::Checked == nState)
	{
		QMessageBox::information(this, QStringLiteral("状态"), QStringLiteral("跑步被选中"));
	}
	else
	{
		QMessageBox::information(this, QStringLiteral("状态"), QStringLiteral("跑步部分选中"));
	}
		
}

void Qt7ButtonsApp::on_rbtnFemale_clicked()
{
	QMessageBox::information(this, QStringLiteral("性别"), QStringLiteral("选择女"));
}

void Qt7ButtonsApp::buttonGroupSlot(int nID)
{
	// 判断逻辑方式1
	if (m_pButtonGroup->button(nID)->isChecked())
	{
		QString strText = m_pButtonGroup->button(nID)->text();
		qDebug() << strText;
	}

	// 判断逻辑方式2
	switch (nID)
	{
	case 0:
		m_bGender = true;
		qDebug() << QStringLiteral("选择了女");
		break;
	case 1:
		m_bGender = false;
		qDebug() << QStringLiteral("选择了男");
	default:
		break;
	}
}

void Qt7ButtonsApp::provinceComboBoxChangedSlot(int nIndex)
{
	// 获取当前选择项的文本
	//QString strText = ui.cbxProvince->currentText();
	QString strText = ui.cbxProvince->itemText(nIndex);
	ui.label->setText(strText);
	qDebug() << nIndex;
}

void Qt7ButtonsApp::provinceComboBoxChangedStringSlot(QString strText)
{
	ui.label->setText(strText);
}

void Qt7ButtonsApp::on_cbxProvince_currentIndexChanged(int nIndex)
{
	// QVariant转换为QString
	QString strText = ui.cbxProvince->currentData().toString();
	// 给QLabel设置文本
	ui.label->setText(strText);
	qDebug() << ui.cbxProvince->count();
}

void Qt7ButtonsApp::on_cbxFont_currentFontChanged(const QFont &font)
{
	//将QLabel上的文本设置为当前选择的字体
	ui.labelFont->setFont(font);
}

void Qt7ButtonsApp::on_lineEditNormal_editingFinished()
{
	ui.labelText->setText(ui.lineEditNormal->text());
}

void Qt7ButtonsApp::on_btnSetText_clicked()
{
	ui.textEdit->insertPlainText(QStringLiteral("求去山西五台山及山西太原周边景点的旅游攻略！如何选择出游方式？求资深驴友给点建议！准备去山西旅游怎么玩好？山西有哪些经典必去景点？哪些景点需要提前预订门票？路线行程怎么样安排合理？有没有山西当地导游麻烦给推荐下。"));
}

void Qt7ButtonsApp::on_btnGetText_clicked()
{
	QMessageBox::information(this, QStringLiteral("文本"), ui.textEdit->toPlainText());
}

void Qt7ButtonsApp::on_textEdit_textChanged()
{
	// 每次插入内容输入焦点（光标）自动移动到末尾
	ui.textEdit->moveCursor(QTextCursor::End);
}

void Qt7ButtonsApp::on_btnRegexp_clicked()
{
	// 匹配1位或2位数字
	QRegularExpression reg("^\\d\\d?$");
	QString strNum = "3";
	int nIndex = strNum.indexOf(reg);
	qDebug() << nIndex;
	strNum = "5b";
	qDebug() << strNum.indexOf(reg);

	//作业： 写正则表达式匹配 mail或letter单词
	reg.setPattern("\\b(mail|letter)\\b");
	strNum = "letter";
	qDebug() <<"strNum="<< strNum.indexOf(reg);

}

void Qt7ButtonsApp::on_btnReadDateTime_clicked()
{
	// 将当前时间日期设置显示到两种控件上面
	QDateTime dateTime = QDateTime::currentDateTime();
	ui.timeEdit->setTime(dateTime.time());
	ui.lineEditTime->setText(dateTime.toString("HH:mm:ss"));

	ui.dateEdit->setDate(dateTime.date());
	ui.lineEditDate->setText(dateTime.toString("yyyy/M/d"));

	ui.dateTimeEdit->setDateTime(dateTime);
	ui.lineEditDateTime->setText(dateTime.toString("yyyy/M/d HH:mm:ss"));
}

void Qt7ButtonsApp::on_btnSetTime_clicked()
{
	QString strTime = ui.lineEditTime->text();
	strTime.trimmed();
	if (!strTime.isEmpty())
	{
		// 将字符串转换为QTime类型
		QTime tm = QTime::fromString(strTime,"HH:mm:ss");
		ui.timeEdit->setTime(tm);
	}
}

void Qt7ButtonsApp::on_btnSetDate_clicked()
{
	QString strDate = ui.lineEditDate->text();
	strDate.trimmed();
	if (!strDate.isEmpty())
	{
		QDate dt = QDate::fromString(strDate, "yyyy/M/d");
		ui.dateEdit->setDate(dt);
	}
}

void Qt7ButtonsApp::on_btnSetDateTime_clicked()
{
	QString strDateTime = ui.lineEditDateTime->text();
	strDateTime.trimmed();
	if (!strDateTime.isEmpty())
	{
		// 注意：fromString()参数2的格式要与控件属性displayFormat保持一致
		QDateTime dateTime = QDateTime::fromString(strDateTime, "yyyy/M/d HH:mm:ss");
		ui.dateTimeEdit->setDateTime(dateTime);
	}

}

void Qt7ButtonsApp::sliderValueChangeSlot()
{
	// 获取滑块值
	int nRed = ui.hsRed->value();
	int nGreen = ui.hsGreen->value();
	int nBlue = ui.hsBlue->value();

	QColor color(nRed, nGreen, nBlue);
	QPalette pal = ui.textEditBackColor->palette();
	pal.setBrush(QPalette::Base, color);
	ui.textEditBackColor->setAutoFillBackground(true);
	ui.textEditBackColor->setPalette(pal);
}

void Qt7ButtonsApp::on_spinBox_valueChanged(QString strText)
{
	// 修改旋转框的值时，蓝色滑块的值会改变
	ui.hsBlue->setValue(strText.toInt());
}
void Qt7ButtonsApp::testFunction()
{
	
}
